<?

class bf_url {

	protected $opts;
	protected $location;

	public function __construct($options = array()) {

		$port = $this->get_port();
		$this->location = $this->get_schema() . '://' . $this->get_host() . (!in_array($port, array(80, 443)) ? ':' . $port : '') . $this->get_root() . '/';

		$this->opts = array_merge(array(
			'friendly' => (isset($_GET['url-rewrited']) ? true : false),
			'routes' => array(),
		), $options);

	}

	public static function get_schema() { return (isset($_SERVER['HTTPS']) && preg_match('/^\s*(on|yes|true|1)\s*$/i', $_SERVER['HTTPS']) ? 'https' : 'http'); }

	public static function get_host() {
		$server_name = (isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : (isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : 'localhost'));
		$server_name = preg_replace('/\:\d+$/', '', $server_name);
		return $server_name;
	}

	public static function get_port() {
		return (isset($_SERVER['SERVER_PORT']) ? $_SERVER['SERVER_PORT'] : 80); // TODO check value for https connection
	}

	public static function get_root() {
		$documents_root = bf_path::expand($_SERVER['DOCUMENT_ROOT']);
		$this_file = bf_path::expand(__FILE__);
		$root = (strpos($this_file, $documents_root) === false ? '/' : dirname(substr($this_file, strlen($documents_root))));
		$root = dirname(dirname($root));
		$root = preg_replace("/\\\\+/", '/', $root);
		$root = preg_replace("/\/+$/", '', $root);
		return $root;
	}

	public function base($schema = false) { return ($schema ? preg_replace('/^[^:]+\:\/\//', $schema . '://',  $this->location) : $this->location); }

	public function is_friendly() { return $this->opts['friendly']; }

	public function clear() { $this->opts['routes'] = array(); }

	public function escape($str) { return urlencode($str); }
	public function unescape($str) { return urldecode($str); }

	/*

		users/123/comments/2011-08-29/2011-09-01
			-> users.php?id=123&show=comments&since=2011-08-29&till=2011-09-01

		'/^(?P<controller>\w+)\/(?P<id>\d+)\/(?P<show>\w+)\/(?P<since>\d{4}-\d\d-\d\d)\/(?P<till>\d{4}-\d\d-\d\d)\/?$/'
			-> '$controller.php?id=$id&show=$show&since=$since&till=$till'
	*/

	public function set($route, $rule = false) {
		if (is_array($route) && $rule === false) {
			foreach ($route as $rt => $rl)
				$this->set($rt, $rl);
		} else {
			$this->opts['routes'][$route] = $rule;
		}
	}

	public function get($url, $schema = false) {

                if (!$this->is_friendly()) {
			$params = array();
			foreach ($this->opts['routes'] as $route => $rule) {
				if (preg_match($route, $url, $params)) {
					$this->params = $params;
					$result = preg_replace_callback('/\$([a-z][a-z0-9_]*)/i', array($this, 'get_param'), $rule);
					$this->params = null;
					return preg_replace('/\/+$/', '/', $this->base($schema)) . preg_replace('/^\/+/', '', $result);
				}
			}
		}

		return preg_replace('/\/+$/', '/', $this->base($schema)) . preg_replace('/^\/+/', '', $url);
	}

	public function rewrite($url) {

		$result = false;
		$params = array();
		foreach ($this->opts['routes'] as $route => $rule) {
			if (preg_match($route, (string) $url, $params)) {
				$this->params = $params;
				$result = preg_replace_callback('/\$([a-z][a-z0-9_]*)/i', array($this, 'get_param'), $rule);
				$this->params = null;
				break;
			}
		}

		if ($result) {
			$parts = explode('?', $result, 2);
			$file = $parts[0];
			$sparams = @$parts[1];
			$params = array();
			if ($sparams)
				parse_str($sparams, $params);
			return array('file' => $file, 'params' => $params, 'url' => $result);
		}
	}

	private function get_param($matches) { return @$this->params[$matches[1]]; }
}

?>